package boardgamer.yavalath.client.replay;

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LightingColorFilter;
import android.graphics.Paint;
import android.graphics.RectF;
import android.view.MotionEvent;
import boardgamer.common.client.Button;
import boardgamer.common.client.ClickableButton;
import boardgamer.common.client.SimpleButton;
import boardgamer.common.client.ToggleButton;
import boardgamer.common.client.layout.BitmapLayout;
import boardgamer.common.client.layout.LayoutGroup;
import boardgamer.yavalath.client.pro.ProImageHandler;

import static com.google.common.base.Preconditions.checkNotNull;

/**
 * @author garysoed
 */
public class ReplayControl implements Button {

  private static final float COLLISION_INSET_RATIO = 0.1f;
  
  private final ReplayPlayer player;
  private final Button beginButton;
  private final Button backwardButton;
  private final ToggleButton playPauseButton;
  private final Button forwardButton;
  private final Button endButton;
  private final LayoutGroup group;

  public ReplayControl(final ReplayPlayer player, final Controllable controllable) {
    this.player = checkNotNull(player, "player");

    Paint buttonPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    buttonPaint.setColorFilter(new LightingColorFilter(Color.RED, 0));
    this.beginButton = createClickableButton(
        ProImageHandler.replayBegin,
        ProImageHandler.replayBeginGlow,
        buttonPaint,
        new EventHandler() {
          @Override public void onEvent(float eventX, float eventY, int eventAction) {
            if (eventAction == MotionEvent.ACTION_UP) {
              controllable.begin();
            }
          }
        });
    this.backwardButton = createClickableButton(
        ProImageHandler.replayBackward,
        ProImageHandler.replayBackwardGlow,
        buttonPaint,
        new EventHandler() {
          @Override public void onEvent(float eventX, float eventY, int eventAction) {
            if (eventAction == MotionEvent.ACTION_UP) {
              controllable.backOne();
            }
          }
        });
    this.forwardButton = createClickableButton(
        ProImageHandler.replayForward,
        ProImageHandler.replayForwardGlow,
        buttonPaint,
        new EventHandler() {
          @Override public void onEvent(float eventX, float eventY, int eventAction) {
            if (eventAction == MotionEvent.ACTION_UP) {
              controllable.forwardOne();
            }
          }
        });
    this.endButton = createClickableButton(
        ProImageHandler.replayEnd,
        ProImageHandler.replayEndGlow,
        buttonPaint,
        new EventHandler() {
          @Override public void onEvent(float eventX, float eventY, int eventAction) {
            if (eventAction == MotionEvent.ACTION_UP) {
              controllable.end();
            }
          }
        });
    this.playPauseButton = new ToggleButton(
        createClickableButton(
            ProImageHandler.replayPause,
            ProImageHandler.replayPauseGlow,
            buttonPaint,
            new EventHandler() {
              @Override public void onEvent(float eventX, float eventY, int eventAction) {
                if (eventAction == MotionEvent.ACTION_UP) {
                  player.setPlaying(false);
                }
              }
            }),
        createClickableButton(
            ProImageHandler.replayPlay,
            ProImageHandler.replayPlayGlow,
            buttonPaint,
            new EventHandler() {
              @Override public void onEvent(float eventX, float eventY, int eventAction) {
                if (eventAction == MotionEvent.ACTION_UP) {
                  player.setPlaying(true);
                }
              }
            }),
        player.isPlaying());  // isActive
    
    this.group = new LayoutGroup()
        .add(beginButton).atCurrentRect()
        .add(backwardButton).relativeToEdge(beginButton, LayoutGroup.Direction.RIGHT, 0)
        .add(playPauseButton).relativeToEdge(backwardButton, LayoutGroup.Direction.RIGHT, 0)
        .add(forwardButton).relativeToEdge(playPauseButton, LayoutGroup.Direction.RIGHT, 0)
        .add(endButton).relativeToEdge(forwardButton, LayoutGroup.Direction.RIGHT, 0);
  }
  
  private Button createClickableButton(Bitmap bitmap, Bitmap glowBitmap, Paint buttonPaint,
      EventHandler eventHandler) {
    BitmapLayout bitmapLayout = new BitmapLayout(bitmap, buttonPaint);
    RectF collisionBox = bitmapLayout.getBoundingRect();
    collisionBox.inset(
        collisionBox.width() * COLLISION_INSET_RATIO,
        collisionBox.height() * COLLISION_INSET_RATIO);
    return new ClickableButton(
        new SimpleButton(bitmapLayout, eventHandler, collisionBox),
        new BitmapLayout(glowBitmap, buttonPaint));
  }

  @Override
  public void draw(Canvas canvas) {
    playPauseButton.draw(canvas);
    if (!player.isPlaying()) {
      beginButton.draw(canvas);
      backwardButton.draw(canvas);
      forwardButton.draw(canvas);
      endButton.draw(canvas);
    }
  }

  @Override
  public void handleEvent(float eventX, float eventY, int eventAction) {
    playPauseButton.handleEvent(eventX, eventY, eventAction);
    if (!player.isPlaying()) {
      beginButton.handleEvent(eventX, eventY, eventAction);
      backwardButton.handleEvent(eventX, eventY, eventAction);
      forwardButton.handleEvent(eventX, eventY, eventAction);
      endButton.handleEvent(eventX, eventY, eventAction);
    }
  }

  @Override
  public RectF getCollisionBox() {
    return getBoundingRect();
  }

  @Override
  public void setBoundingRect(RectF boundingRect) {
    group.setBoundingRect(boundingRect);
  }

  @Override
  public RectF getBoundingRect() {
    return group.getBoundingRect();
  }
  
  public void setPlaying(boolean isPlaying) {
    if (isPlaying ^ playPauseButton.isActive()) {
      playPauseButton.toggleDisplay();
      player.setPlaying(isPlaying);
    }
  }

  public interface Controllable {

    void begin();

    void backOne();

    void forwardOne();

    void end();
  }
}
